#import <objc/runtime.h>
#import "MRViewController.h"

#define	UIViewControllerCreate		@"createViewController"
#define	UIViewControllerBack		@"backViewController"

#pragma mark - 标准视图控制器扩展
@implementation UIViewController (Extension)
@dynamic created, backViewController;

+ (void)load
{
	Method fun = class_getInstanceMethod(self, @selector(viewDidLoad));
	Method new = class_getInstanceMethod(self, @selector(fsViewDidLoad));
	method_exchangeImplementations(fun, new);
	
	fun = class_getInstanceMethod(self, @selector(viewWillAppear:));
	new = class_getInstanceMethod(self, @selector(fsViewWillAppear:));
	method_exchangeImplementations(fun, new);
	
	fun = class_getInstanceMethod(self, @selector(viewWillDisappear:));
	new = class_getInstanceMethod(self, @selector(fsViewWillDisappear:));
	method_exchangeImplementations(fun, new);
}

- (void)fsViewDidLoad
{
	[self fsViewDidLoad];
}

- (void)fsViewWillAppear:(BOOL)animated
{
	[self fsViewWillAppear:animated];
	
	if (!self.created)
	{
		//地图及集合视图约束于导航右滑返回手势
		__weak MRNavigationController *nvc = (MRNavigationController *)self.navigationController;
		if ([nvc isKindOfClass:[MRNavigationController class]])
		{
			[self.view viewWithClass:[UICollectionView class] handler:^(UICollectionView *view, BOOL *stop) {
				[view.panGestureRecognizer requireGestureRecognizerToFail:nvc.panGestureRecognizer];
			}];
		}
		
		//处理返回按钮
		if (self.navigationItem.leftBarButtonItem == nil && self.parentViewController == self.navigationController && self.navigationController.viewControllers.count > 1)
		{
			[self.navigationItem setLeftBarButtonItem:[UIBarButtonItem initBackWithTitle:nil target:self action:@selector(cancel)]];
		}
		
		if (!IOS8 && self.navigationController)
		{
			//IOS7中导航栏不允许约束，否则会报错。
			[self.view viewWithClass:[UINavigationBar class] handler:^(UIView *view, BOOL *stop) {
				
				[view disableConstraint];
				*stop = YES;
				
				for (UIView *v in view.subviews) [v disableConstraint];
			}];
		}
		
		if (self.navigationController) [self.view layoutIfNeeded];
		[self viewWillCreate];		//创建里执行添加或删除视图操作
		
		[self setNeedsStatusBarAppearanceUpdate];
		objc_setAssociatedObject(self, UIViewControllerCreate, @YES, OBJC_ASSOCIATION_ASSIGN);
		
		//语言更改通知
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidLanguage) name:APPLANGUAGE object:nil];
	}
	
	[self registerForLastPreviewing];
}

- (void)fsViewWillDisappear:(BOOL)animated
{
	[self fsViewWillDisappear:animated];
	[self unregisterForPreviewing];
}

#pragma mark - 3D Touch
- (void)registerForLastPreviewing
{
	id previewing = objc_getAssociatedObject(self, @"previewing");
	UIView *sourceView = objc_getAssociatedObject(self, @"sourceview");
	
	if (!previewing && sourceView)
	{
		previewing = [self registerForPreviewingWithDelegate:self sourceView:sourceView];
		objc_setAssociatedObject(self, @"previewing", previewing, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
	}
}

- (void)registerForPreviewingWithView:(UIView *)sourceView
{
	if (IOS9)
	{
		objc_setAssociatedObject(self, @"sourceview", sourceView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
		
		if (sourceView)
			[self registerForLastPreviewing];
		else
			[self unregisterForPreviewing];
	}
}

- (void)unregisterForPreviewing
{
	id previewing = objc_getAssociatedObject(self, @"previewing");
	if (previewing)
	{
		[self unregisterForPreviewingWithContext:previewing];
		objc_setAssociatedObject(self, @"previewing", nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
	}
}

#pragma mark - Storyboard
/*===================================================================
 说明:
	加载故事板控制器
 ==================================================================*/
+ (instancetype)storyboardWithName:(NSString *)name storyboardID:(NSString *)sid
{
	if (sid)
		return [[UIStoryboard storyboardWithName:name bundle:nil] instantiateViewControllerWithIdentifier:sid];
	else if (name)
		return [[UIStoryboard storyboardWithName:name bundle:nil] instantiateInitialViewController];
	
	return nil;
}

+ (instancetype)storyboardInitialWithName:(NSString *)name
{
	return [UIViewController storyboardWithName:name storyboardID:nil];
}

- (instancetype)viewControllerWithStoryboardID:(NSString *)sid
{
	return [self.storyboard instantiateViewControllerWithIdentifier:sid];
}

#pragma mark - 控制器新事件
/*===================================================================
 说明:
	控制器创建
 ==================================================================*/
- (void)viewWillCreate
{
	//
}

- (void)viewWillDealloc
{
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	objc_removeAssociatedObjects(self);
	
	//DLog(@"dealloc: %@", self);
}

- (void)viewDidLanguage
{
	//
}

#pragma mark - 控制器新属性
/*===================================================================
 说明:
	返回控制器属性(扩展属性) Associative机制
 ==================================================================*/
- (void)setBackViewController:(UIViewController *)backViewController
{
	objc_setAssociatedObject(self, UIViewControllerBack, backViewController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIViewController *)backViewController
{
	return objc_getAssociatedObject(self, UIViewControllerBack);
}
//===================================================================
- (BOOL)created
{
	return [objc_getAssociatedObject(self, UIViewControllerCreate) boolValue];
}

#pragma mark - 控制器操作
/*===================================================================
 说明:
	返回或取消当前控制器
 ==================================================================*/
- (void)cancel
{
	[self cancelWithAnimated:YES];
}

- (void)cancelWithAnimated:(BOOL)animated
{
    UIViewController *vc = self;
    
	if (vc.parentViewController)
	{
        if ([vc.parentViewController isKindOfClass:[UINavigationController class]])
        {
            vc = vc.parentViewController;
            UINavigationController *nvc = (UINavigationController *)vc;
            
            NSInteger index = [nvc.viewControllers indexOfObject:self];
            if (index)   //当前不是导航控制器的根视图时，返回到本视图的上一视图
            {
				dispatch_after(.1, dispatch_get_main_queue(), ^{
					[nvc popToViewController:nvc.viewControllers[index - 1] animated:animated];
				});
                return;
            }
        }
        else
        {
            [vc.parentViewController cancelWithAnimated:animated];
            return;
        }
	}
	
	//没有父控制器时则检查是否为弹出窗口，根据情况取消显示
	__block UIWindow *window = objc_getAssociatedObject(vc, @"popupWindow");
	if (window)
	{
		PopupHandler handler = objc_getAssociatedObject(vc, @"popupHandler");
		if (handler) handler();
		
		[UIView animateWithDuration:(animated ? .25 : 0) animations:^{
			window.alpha = 0;
		} completion:^(BOOL finished) {
			window.hidden = YES;
			window.rootViewController = nil;
			objc_removeAssociatedObjects(vc);
		}];
	}
	else if (vc.presentingViewController)
	{
		dispatch_after(.1, dispatch_get_main_queue(), ^{
			[vc dismissViewControllerAnimated:animated completion:nil];
		});
	}
}

/*===================================================================
 说明:
	弹出独立窗口(非模态)
 ==================================================================*/
+ (void)showViewController:(UIViewController *)target
{
	[UIViewController showViewController:target animated:YES handler:nil];
}

+ (UIWindow *)showViewController:(UIViewController *)target animated:(BOOL)animated handler:(PopupHandler)handler
{
	UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
	window.alpha = 0;
	window.backgroundColor = [UIColor clearColor];
	window.rootViewController = target;
	window.hidden = NO;
	
	objc_setAssociatedObject(target, @"popupWindow", window, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
	objc_setAssociatedObject(target, @"popupHandler", handler, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
	
	[UIView animateWithDuration:(animated ? .25 : 0) animations:^{
		window.alpha = 1;
	}];
	
	return window;
}

/*===================================================================
 说明:
	显示指定窗体,动画完成后当前导航跳转到指定视图
 ==================================================================*/
- (void)showViewController:(UIViewController *)target after:(UIViewController *)viewController animated:(BOOL)animated
{
	if (target)
	{
		UIViewController *vc = self;
		while (vc.parentViewController) vc = vc.parentViewController;
		
		__weak UIViewController *this = self;
		[vc presentViewController:target animated:animated completion:^{
			if (viewController)
				[this.navigationController popToViewController:viewController animated:NO];
		}];
	}
}

- (void)showViewController:(UIViewController *)target
{
	[self showViewController:target after:nil animated:YES];
}

/*===================================================================
 说明:
	压入指定窗体， after控制器会保持到下次有after值的控制器
 ==================================================================*/
- (void)pushViewController:(UIViewController *)target after:(UIViewController *)viewController
{
	if (target)
	{
		target.backViewController = viewController;
		[self.navigationController pushViewController:target animated:YES];
	}
}

- (void)pushViewController:(UIViewController *)target
{
	[self pushViewController:target after:nil];
}

@end

#pragma mark - 自定视图控制器
/*===================================================================
 说明:
	自定视图控制器
 ==================================================================*/
@implementation MRViewController

- (id)initWithTitle:(NSString *)title view:(UIView *)view
{
	if (self = [super init])
	{
		self.navigationItem.title = title;
		if (view) self.view = view;
	}
	return self;
}

- (void)viewDidLoad
{
	[super viewDidLoad];
	self.view.backgroundColor = [MRSkinManager skin].backgroundColor;
}

/*===================================================================
 说明:
    屏幕方向支持
 ==================================================================*/
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

/*===================================================================
 说明:
	状态栏样式
 ==================================================================*/
- (UIStatusBarStyle)preferredStatusBarStyle
{
	return [MRSkinManager skin].statusBarStyle;
}

@end
